#pragma once

// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

// Color.h : interface of the Color class
//


#include <string>
#include "SmartEnum.h"

inline float colorComp(int comp) 
{   
    return comp / 256.0f;
}

BEGIN_ENUM(ColorId)
    Red, Green, Blue, Orange, Brown, Yellow, GreenYellow,
    Pink, Cyan, Magenta, Black, Grey192, Grey128, Grey64, White, 
    DarkGreen, DarkBlue, LightGreen, LightBlue,
    Purple, Beige, PaleGoldenRod, Gold, Coral
END_ENUM(ColorId)

class Color;
Color getColorFromId(ColorId id, float opacity=1.);
void colorFromId(ColorId id, float opacity=1.);

Color getColorFromName(std::string const & color_name, float opacity=1.);
void colorFromName(std::string const & name, float opacity=1.);
    
typedef void ColorCallback(float r, float g, float b, float a);
extern ColorCallback * __color_callback;
void setColorCallback(ColorCallback * cb);

class Color
{
public:
    float rgba[4];
    Color();
    Color(float r, float g, float b, float a=1.);
    Color(float const src[], int n);
    Color(ColorId id, float opacity=1.);
    Color(std::string const & name, float opacity=1.);
    void from_id(ColorId id, float opacity=1.);
    void from_name(std::string const & name, float opacity=1.);
    float const & operator[](int i) const; 
    float & operator[](int i); 
    const float * to_array() const; 
    void copy_to(float dest[4]); 
    void operator()() const; 
    void operator()(float opacity) const;  
    static Color interp(Color const & from, Color const & to, float x);
};

inline std::wostream& operator<<(std::wostream& os, const Color& color)
{
    return os << color.rgba[0] << " " << color.rgba[1] << " " 
        << color.rgba[2] << " " << color.rgba[3];
}

inline std::wistream& operator>>(std::wistream& is, Color& color)
{
    return is >> color.rgba[0] >> color.rgba[1] 
              >> color.rgba[2] >> color.rgba[3];
}

Color makeBrighter(Color const & color, int times=1);
Color makeDarker(Color const & color, int times=1);


#define MPG_GEN_COLOR(name, r, g, b)                               \
inline Color get##name(float opacity = 1)                          \
{   return Color(r, g, b, opacity);                                 \
}                                                                   \
inline void name(float opacity = 1)                                 \
{   if(__color_callback)                                            \
        __color_callback(r, g, b, opacity);                         \
}  
 
#define MPG_GEN_COLOR_HEX(name, r, g, b)                                                     inline Color get##name(float opacity = 1)                                                  \
{                                                                                          \
    return Color(colorComp(0x##r), colorComp(0x##g), colorComp(0x##b), opacity);           \
}                                                                                          \
inline void name(float opacity = 1)                                                        \
{                                                                                          \
    if(__color_callback)                                                                   \
        __color_callback(colorComp(0x##r), colorComp(0x##g), colorComp(0x##b), opacity);   \
} 

MPG_GEN_COLOR_HEX(Red, FF, 00, 00)
MPG_GEN_COLOR_HEX(DarkRed, 8B, 00, 00)

MPG_GEN_COLOR_HEX(Green, 00, FF, 00)
MPG_GEN_COLOR_HEX(DarkGreen, 00, 64, 00)
MPG_GEN_COLOR_HEX(LightGreen, 90, EE, 90)

MPG_GEN_COLOR_HEX(Blue, 00, 00, FF)
MPG_GEN_COLOR_HEX(DarkBlue, 00, 00, 8B)
MPG_GEN_COLOR_HEX(LightBlue, AD, D8, E6)

MPG_GEN_COLOR(Yellow, 1, 1, 0)
MPG_GEN_COLOR(Magenta, 1, 0, 1)

MPG_GEN_COLOR_HEX(GreenYellow, AD, FF, 2F)	 

MPG_GEN_COLOR_HEX(PaleGoldenRod, EE, E8, AA)
MPG_GEN_COLOR_HEX(Beige, F5, F5, DC)
MPG_GEN_COLOR_HEX(Purple, 80, 00, 80)
MPG_GEN_COLOR_HEX(Gold, FF, D7, 00)	 
MPG_GEN_COLOR_HEX(Coral, FF, 7F, 50)

MPG_GEN_COLOR(Cyan, 0, 1, 1)
MPG_GEN_COLOR_HEX(Pink, FF, C0, CB)
MPG_GEN_COLOR(Orange, 1, 0.5, 0)
MPG_GEN_COLOR_HEX(Brown, A5, 2A, 2A)

MPG_GEN_COLOR(White, 1, 1, 1)
MPG_GEN_COLOR(Black, 0, 0, 0)

MPG_GEN_COLOR_HEX(Grey64,  40, 40, 40)
MPG_GEN_COLOR_HEX(Grey128, 80, 80, 80)
MPG_GEN_COLOR_HEX(Grey192, C0, C0, C0)

inline Color getGrey(float shade, float opacity=1.)
{   
    return Color(shade, shade, shade, opacity);
}

inline void grey(float shade, float opacity=1.)
{   
    if(__color_callback)
    {
        __color_callback(shade, shade, shade, opacity);
    }
}
    
#undef MPG_GEN_COLOR_HEX
#undef MPG_GEN_COLOR    

